package com.lzq.course.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * 自定义过滤器
 * 控制台拦截请求
 */
@Component
public class LoginAdminGatewayFilter implements GatewayFilter, Ordered {

    private final static Logger LOG = LoggerFactory.getLogger(LoginAdminGatewayFilter.class);

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.判断是否属于控制台请求
        String path = exchange.getRequest().getURI().getPath();
        if (!path.contains("/admin/")) {
            return chain.filter(exchange); // 不需要拦截  如果有多个过滤器 继续执行
        }
        if (path.contains("/system/admin/user/login")
                || path.contains("/system/admin/user/logout")
                || path.contains("/system/admin/kaptcha")) {
            LOG.info("不需要拦截放行请求：{}", path);
            return chain.filter(exchange);
        }

        // 2.获取header的 token
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (token == null || token.isEmpty()) {
            LOG.info("登录token为空：请求被拦截");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); // 401 未授权
            return exchange.getResponse().setComplete();
        }
        Object object = redisTemplate.opsForValue().get(token); // 用户登录信息
        if (object == null) {
            LOG.info("登录token无效：请求被拦截");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        } else {
            LOG.info("已登录：请求放行");

            // 增加接口权限校验 gateway没有loginUserDto 全部使用JSON操作
            LOG.info("请求接口：{}", path);
            boolean exists = false; // 默认：权限不存在
            JSONObject loginUserDto = JSON.parseObject(String.valueOf(object));
            JSONArray requests = loginUserDto.getJSONArray("requests");
            // 遍历该用户所有的权限请求， 判读当前请求是否包含在请求里
            for (int i = 0; i < requests.size(); i++) {
                String request = requests.getString(i);
                if (path.contains(request)) {
                    exists = true;
                    break;
                }
            }
            if (exists) {
                LOG.info("权限校验通过：请求放行");
            } else {
                LOG.info("权限校验不通过：请求被拦截");
                // 返回 401
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    }

    @Override
    public int getOrder() {
        return 1; // 过滤器顺序
    }
}
